package donkeykong;

import java.awt.Color;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import javax.sound.sampled.Clip;
import javax.swing.Timer;

/**
 * 
 * @author Antonio Cebollada, Miguel Castillo, José Ignacio Castro
 *
 */
public class Saltar implements Runnable, ActionListener{

	private Mario mario;
	private BufferedImage imagenFondo;
	private Timer t;
	/** Incremento en el eje X durante el salto **/
	int incremento_x = 0;
	
	/** Constante para el movimiento en X **/
	private int MOVIMIENTO_X = 0;
	/** Constante para el movimiento en Y **/
	private int MOVIMIENTO_Y = 0;
	/** Maxima distancia para que no muera Mario en el salto **/
	final int DISTANCIA_MUERTO = 30;
	private boolean en_ascensor;
	
	/** Pantalla actual **/
	private int pantalla;
	
	private ArrayList<Ascensor> ascensores1;
	private ArrayList<Ascensor> ascensores2;
	private boolean quieroBreak;
	private Ascensor ascensorMarioSubido;
	
	private boolean[][] Plataform;
	private Sueloespecial[][] Conj;
	private Puntuacion_total score;
	
	
	public Saltar(Mario m, Image image, int pant) {
		pantalla=pant;
		mario = m;
		imagenFondo = (BufferedImage) image;
		t = new Timer(50,this);
		t.start();
		setEn_ascensor(false);
	}
	
	public Saltar(Mario m, Image image, ArrayList<Ascensor> asc1, ArrayList<Ascensor> asc2, int pant ) {
		pantalla = pant;
		mario = m;
		imagenFondo = (BufferedImage) image;
		t = new Timer(50,this);
		t.start();
		setEn_ascensor(false);
		ascensores1 = asc1;
		ascensores2 = asc2;
	}
	
	public Saltar(Mario m, Image image, Sueloespecial[][] conj, boolean[][] Plataformas, int pant, Puntuacion_total sc ) {
		score = sc;
		pantalla = pant;
		mario = m;
		imagenFondo = (BufferedImage) image;
		t = new Timer(50,this);
		t.start();
		Conj=conj;
		Plataform=Plataformas;
		
	}
	

	@Override
	public void run() {

		
		if (pantalla==1){
			
			MOVIMIENTO_X = 4;
			MOVIMIENTO_Y = 4;
			
			/** Guardarse la posicion desde la que saltas para comprobar despues si caes de mucha altura **/
			int posicion_inicial_y = mario.getPosicion_y();
			/** Si no te estas moviendo durante el salto, no debes moverte en el eje X. Si te mueves, moverte cada vez un cierto valor **/
			if (mario.isMoviendose()){
			   incremento_x = (mario.MirandoDcha()? MOVIMIENTO_X: -MOVIMIENTO_X);
			}
			int incremento_y = MOVIMIENTO_Y;		
			
			/** Indicar que se esta saltando, y poner un movimiento en x, y para el salto, para el eje y debe restarse porque primero subes **/
			mario.setSaltando(true);
			mario.setIncrementoSalto(-incremento_y);
			mario.setDesplazamientoSalto(incremento_x);
			
			/** Esperar 0.6 segundos para que suba en el salto **/
				try {
					Thread.sleep(600);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			
			/** Coger el color del pixel que se encuentra justo en el centro de la base de la imagen del Mario **/
			int c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y());
			Color color = new Color(c1);

			while (!(mario.EsSuelo(color))){
				
				if(!mario.isMuriendo()){
					 int j=1;
					 mario.setIncrementoSalto(incremento_y);
					 
					 
					 /** Hacemos otro bucle para ir pixel a pixel en vez de los que baja de vez, para hacer un barrido exacto de donde esta el suelo
					  * y tambien para hacer que caiga mas lento a medida que se acerca el suelo, para que no pueda pasarlo de largo **/
					 for (j=1;j<=incremento_y;j++){
						 
						 if(!mario.isMuriendo()){
							 c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y()+j);
							 color = new Color(c1);				 
							 if (mario.EsSuelo(color)){
								 incremento_y = j;
							 }
							 
						 }else{
							 mario.setIncrementoSalto(0);
							 mario.setDesplazamientoSalto(0);
							 mario.setSaltando(false);
							 break;
						 }
					 }
					
					 
					 c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y());
					 color = new Color(c1);		
					 
				}else{
					 mario.setIncrementoSalto(0);
					 mario.setDesplazamientoSalto(0);
					 mario.setSaltando(false);
					 break;				
					 }
			}
			
			/** Nos guardamos la posicion en el eje Y de Mario una vez ha caido **/
			int posicion_final_y = mario.getPosicion_y();
			
			/** Si la diferencia desde donde empieza a saltar a donde acaba es mayor a 30,  muerto **/
			if (Math.abs(posicion_final_y-posicion_inicial_y) > DISTANCIA_MUERTO){   
				/** Si esta muerto, parar la musica, y realizar el tratamiento de Mario muerto. **/
				mario.pararSonido();
				mario.Muriendo();
			}
	
			/** Si Mario no esta muriendo, poner que ya deja de saltar **/
			if (!mario.isMuriendo()){
				
				mario.setSaltando(false);
				
				/** Reproducir sonido de caminar si se esta presionando la tecla de moverse **/
				if (mario.isMoviendose() & !mario.isSaltando()){
					mario.escucharSonido("walking", Clip.LOOP_CONTINUOUSLY);
				}
				t.stop();
	
			}
				/** Quitar los incrementos de movimiento de salto **/
				mario.setIncrementoSalto(0);
				mario.setDesplazamientoSalto(0);
				t.stop();
			
			
		}else if (pantalla==2){
			MOVIMIENTO_X = 6;
			MOVIMIENTO_Y = 5;
			
			
			boolean salir=false;
			
			/** Guardarse la posicion desde la que saltas para comprobar despues si caes de mucha altura **/
			int posicion_inicial_y = mario.getPosicion_y();
			/** Si no te estas moviendo durante el salto, no debes moverte en el eje X. Si te mueves, moverte cada vez un cierto valor **/
			if (mario.isMoviendose()){
			   incremento_x = (mario.MirandoDcha()? MOVIMIENTO_X: -MOVIMIENTO_X);
			}
			int incremento_y = MOVIMIENTO_Y;		
			
			/** Indicar que se esta saltando, y poner un movimiento en x, y para el salto, para el eje y debe restarse porque primero subes **/
			mario.setSaltando(true);
			mario.setIncrementoSalto(-incremento_y);
			mario.setDesplazamientoSalto(incremento_x);
			/** Esperar 0.6 segundos para que suba en el salto **/
				try {
					Thread.sleep(600);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			/** Coger el color del pixel que se encuentra justo en el centro de la base de la imagen del Mario **/
			int c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y());
			Color color = new Color(c1);
			
			MOVIMIENTO_X = 1;
			MOVIMIENTO_Y = 7;
			/** Si no te estas moviendo durante el salto, no debes moverte en el eje X. Si te mueves, moverte cada vez un cierto valor **/
			if (mario.isMoviendose()){
			   incremento_x = (mario.MirandoDcha()? MOVIMIENTO_X: -MOVIMIENTO_X);
			}
			 incremento_y = MOVIMIENTO_Y;		
			/** Esta parte permite a mario saltar estando encima del ascensor. Lo que miramos es si está encima de alguno
			 * de los ascensores, en cuyo caso lo que se hace es no mirar la posición final, que antes si se hacía y eso era la causa
			 * por la que saltaba y moría al hacerlo, ya que al guardarse la coordenada y e ir aumentando por el efecto del ascensor,
			 * superabas el umbral maximo de caida
			 */
			quieroBreak = false;
			for (int i=0;i<ascensores1.size();i++){
				if (ascensores1.get(i) != null){
					if (ascensores1.get(i).getPosicionY() > 235){
						if (ascensores1.get(i).isEn_ascensor_1()){
							quieroBreak = true;
							ascensorMarioSubido=ascensores1.get(i);
						}
					}
				}
				
			}
			for (int i=0;i<ascensores2.size();i++){
				if (ascensores2.get(i) != null){
					if (ascensores2.get(i).getPosicionY() < 595){
						if (ascensores2.get(i).isEn_ascensor_2()){
							quieroBreak = true;
							ascensorMarioSubido=ascensores2.get(i);
						}
					}
				}
			}
			if (quieroBreak){
				
				while (!(mario.EsSuelo(color))){

					if (mario.getPosicion_y() - posicion_inicial_y > 9){
						incremento_x=0;
						mario.setDesplazamientoSalto(incremento_x);
					}
					
					
					
					if (salir){
						break;
					}
					
					
					if(!mario.isMuriendo()){
						 int j=1;
						 mario.setIncrementoSalto(incremento_y);
						 
						 
						 /** Hacemos otro bucle para ir pixel a pixel en vez de los que baja de vez, para hacer un barrido exacto de donde esta el suelo
						  * y tambien para hacer que caiga mas lento a medida que se acerca el suelo, para que no pueda pasarlo de largo **/
						 for (j=1;j<=incremento_y;j++){
							 
							 
							 
							 
							 if(!mario.isMuriendo()){
								 c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y()+j);
								 color = new Color(c1);				 
								 if (mario.EsSuelo(color)){
									 incremento_y = j;
								 }
								 
								 /** Si mario se choca con la base del ascensor , muere **/
								 
								 if (mario.EsBaseAscensor(color)){
									 mario.pararSonido();
										mario.Muriendo();
										salir=true;
										break;
								 }
								 
								 if (Math.abs(ascensorMarioSubido.getPosicionY()-ascensorMarioSubido.getImage().getHeight(null) - mario.getPosicion_y()) < 2){
									 mario.setIncrementoSalto(0);
									 mario.setDesplazamientoSalto(0);
									 mario.setSaltando(false);
									 t.stop();
									 salir=true;
									 break;		 
								 }
								 
							 }else{
								 mario.setIncrementoSalto(0);
								 mario.setDesplazamientoSalto(0);
								 mario.setSaltando(false);
								 salir=true;
								 break;
							 }
						 }
						
						 
						 c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y());
						 color = new Color(c1);		
						 
					}else{
						 mario.setIncrementoSalto(0);
						 mario.setDesplazamientoSalto(0);
						 mario.setSaltando(false);
						 break;				
						 }
				}
			}else{
			
			
			/** Mientras no toquemos suelo con la base del mario, que siga bajando **/
			while (!(mario.EsSuelo(color))){
				
				
				if (mario.getPosicion_y() - posicion_inicial_y > 9){
					incremento_x=0;
					mario.setDesplazamientoSalto(incremento_x);
				}
				
				
				
				quieroBreak = false;
				for (int i=0;i<ascensores1.size();i++){
					if (ascensores1.get(i) != null){
						if (ascensores1.get(i).getPosicionY() > 235){
							if (ascensores1.get(i).isEn_ascensor_1()){
								quieroBreak = true;
							}
						}
					}
					
				}
				for (int i=0;i<ascensores2.size();i++){
					if (ascensores2.get(i) != null){
						if (ascensores2.get(i).getPosicionY() < 595){
							if (ascensores2.get(i).isEn_ascensor_2()){
								quieroBreak = true;
							}
						}
					}
				}
				if (quieroBreak){
					break;
				}
				if(!mario.isMuriendo()){
					 int j=1;
					 mario.setIncrementoSalto(incremento_y);
					 
					 
					 /** Hacemos otro bucle para ir pixel a pixel en vez de los que baja de vez, para hacer un barrido exacto de donde esta el suelo
					  * y tambien para hacer que caiga mas lento a medida que se acerca el suelo, para que no pueda pasarlo de largo **/
					 for (j=1;j<=incremento_y;j++){
						 
						 if(!mario.isMuriendo()){
							 c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y()+j);
							 color = new Color(c1);				 
							 if (mario.EsSuelo(color)){
								 incremento_y = j;
							 }
							 
							 /** Si mario se choca con la base del ascensor , muere **/
							 
							 if (mario.EsBaseAscensor(color)){
								 mario.pararSonido();
									mario.Muriendo();
									break;
							 }
							 
						 }else{
							 mario.setIncrementoSalto(0);
							 mario.setDesplazamientoSalto(0);
							 mario.setSaltando(false);
							 break;
						 }
					 }
					
					 
					 c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y());
					 color = new Color(c1);		

				}else{
					 mario.setIncrementoSalto(0);
					 mario.setDesplazamientoSalto(0);
					 mario.setSaltando(false);
					 break;				
					 }
			}
			}
			
			if (! salir){
				/** Nos guardamos la posicion en el eje Y de Mario una vez ha caido **/
				int posicion_final_y = mario.getPosicion_y();
				
				/** Si la diferencia desde donde empieza a saltar a donde acaba es mayor a 30,  muerto **/
				if (posicion_final_y-posicion_inicial_y > DISTANCIA_MUERTO){   
					/** Si esta muerto, parar la musica, y realizar el tratamiento de Mario muerto. **/
					mario.pararSonido();
					mario.Muriendo();
				}
		
				/** Si Mario no esta muriendo, poner que ya deja de saltar **/
				if (!mario.isMuriendo()){
					
					mario.setSaltando(false);
					
					/** Reproducir sonido de caminar si se esta presionando la tecla de moverse **/
					if (mario.isMoviendose() & !mario.isSaltando()){
						mario.escucharSonido("walking", Clip.LOOP_CONTINUOUSLY);
					}
					t.stop();
		
				}
					/** Quitar los incrementos de movimiento de salto **/
					mario.setIncrementoSalto(0);
					mario.setDesplazamientoSalto(0);
					t.stop();
			}
			
		}else if (pantalla == 3){
			
			MOVIMIENTO_X = 5;
			MOVIMIENTO_Y = 4;
			
			/** Guardarse la posicion desde la que saltas para comprobar despues si caes de mucha altura **/
			int posicion_inicial_y = mario.getPosicion_y();
			/** Si no te estas moviendo durante el salto, no debes moverte en el eje X. Si te mueves, moverte cada vez un cierto valor **/
			if (mario.isMoviendose()){
			   incremento_x = (mario.MirandoDcha()? MOVIMIENTO_X: -MOVIMIENTO_X);
			}
			int incremento_y = MOVIMIENTO_Y;		
			
			/** Indicar que se esta saltando, y poner un movimiento en x, y para el salto, para el eje y debe restarse porque primero subes **/
			mario.setSaltando(true);
			mario.setIncrementoSalto(-incremento_y);
			mario.setDesplazamientoSalto(incremento_x);
			
			/** Esperar 0.6 segundos para que suba en el salto **/
			while (Math.abs(posicion_inicial_y-mario.getPosicion_y())<24){
				try {
					Thread.sleep(5);
				} catch (InterruptedException e) {
					// LOL
					e.printStackTrace();
				}
				if((mario.getCentroMario()>182&&mario.getCentroMario()<228)||((mario.getCentroMario()>540&&mario.getCentroMario()<590))){ //Posicion de las plataformas
					int nivel=0,plataf=0;
					int limite1=0;
					int limite2=0;
					boolean valido=true;
					/**Miramos la plataforma*/
					if((mario.getCentroMario()>182&&mario.getCentroMario()<228)){	//Plataformas de la izquierda
						plataf=0;
						limite1=215;
						limite2=192;
					}
					else if((mario.getCentroMario()>540&&mario.getCentroMario()<590)){	//Plataformas de la derecha
						plataf=1;
						limite1=574;
						limite2=551;
					}
					else{
						valido=false;
					}
					/**Miramos el nivel en el que esta*/
					if(mario.getPosicion_y()<=480&&mario.getPosicion_y()>400){		
						nivel=0;					
					}
					else if(mario.getPosicion_y()<=376&&mario.getPosicion_y()>294){
						nivel=1;
					}
					else if (mario.getPosicion_y()<=272&&mario.getPosicion_y()>190){
						nivel=2;
					}
					else if(mario.getPosicion_y()<=168){
						nivel=3;
					}
					else{
						valido=false;
					}
					
					/**Miramos si ya habia pasado o no*/
					if((mario.MirandoDcha()&&(mario.getCentroMario()>limite1)&&(valido))||(!mario.MirandoDcha()&&(mario.getCentroMario()<limite2)&&(valido))){	
						Sueloespecial.escucharMusicaFondo("item_points", 0);
						score.añadirPuntuacion(100);
						Puntuacion_imagen pi = new Puntuacion_imagen(mario, 4);
						Thread t = new Thread(pi);
						t.start();
						Plataform[nivel][plataf]=true;
						Conj[nivel][plataf].setPosicion_x(-1);
						Conj[nivel][plataf].setPosicion_y(-1);
						
					}
				}
				
			}

			
			/** Coger el color del pixel que se encuentra justo en el centro de la base de la imagen del Mario **/
			int c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y());
			Color color = new Color(c1);

			while (!(mario.EsSuelo(color))){
				
				
				if((mario.getCentroMario()>182&&mario.getCentroMario()<228)||((mario.getCentroMario()>540&&mario.getCentroMario()<590))){ //Posicion de las plataformas
					int nivel=-1,plataf=-1;
					int limite1=0;
					int limite2=0;
					boolean valido=true;
					/**Miramos la plataforma*/
					if((mario.getCentroMario()>182&&mario.getCentroMario()<228)){	//Plataformas de la izquierda
						plataf=0;
						limite1=215;
						limite2=192;
					}
					else if((mario.getCentroMario()>540&&mario.getCentroMario()<590)){	//Plataformas de la derecha
						plataf=1;
						limite1=574;
						limite2=551;
					}
					else{
						valido=false;
					}
					
					/**Miramos el nivel en el que esta*/
					if(mario.getPosicion_y()<=480&&mario.getPosicion_y()>400){		
						nivel=0;
						if (mario.getPosicion_y()==480&&!Plataform[nivel][plataf]){
							break;
						}
					}
					else if(mario.getPosicion_y()<=376&&mario.getPosicion_y()>294){
						nivel=1;
						if (mario.getPosicion_y()==376&&!Plataform[nivel][plataf]){
							break;
						}
					}
					else if (mario.getPosicion_y()<=272&&mario.getPosicion_y()>190){
						nivel=2;
						if (mario.getPosicion_y()==272&&!Plataform[nivel][plataf]){
							break;
						}
					}
					else if(mario.getPosicion_y()<=167){
						nivel=3;
						if (mario.getPosicion_y()==167&&!Plataform[nivel][plataf]){
							break;
						}
					}
					else{
						valido=false;
					}
					
					
					/**Miramos si ya habia pasado o no*/
					if((mario.MirandoDcha()&&(mario.getCentroMario()>limite1)&&(valido))||(!mario.MirandoDcha()&&(mario.getCentroMario()<limite2)&&(valido))){	
						Plataform[nivel][plataf]=true;
						Conj[nivel][plataf].setPosicion_x(-1);
						Conj[nivel][plataf].setPosicion_y(-1);
						
					}				
				}
				
				
				
				if(!mario.isMuriendo()){
					 int j=1;
					 mario.setIncrementoSalto(incremento_y);
					 
					 
					 /** Hacemos otro bucle para ir pixel a pixel en vez de los que baja de vez, para hacer un barrido exacto de donde esta el suelo
					  * y tambien para hacer que caiga mas lento a medida que se acerca el suelo, para que no pueda pasarlo de largo **/
					 for (j=1;j<=incremento_y;j++){
						 
						 if(!mario.isMuriendo()){
							 c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y()+j);
							 color = new Color(c1);				 
							 if (mario.EsSuelo(color)){
								 incremento_y = j;
							 }
							 
						 }else{
							 mario.setIncrementoSalto(0);
							 mario.setDesplazamientoSalto(0);
							 mario.setSaltando(false);
							 break;
						 }
					 }
					
					 
					 c1 = imagenFondo.getRGB(mario.getCentroMario(),mario.getPosicion_y());
					 color = new Color(c1);		

				}else{
					 mario.setIncrementoSalto(0);
					 mario.setDesplazamientoSalto(0);
					 mario.setSaltando(false);
					 break;				
					 }
			}
			
			/** Nos guardamos la posicion en el eje Y de Mario una vez ha caido **/
			int posicion_final_y = mario.getPosicion_y();
			
			/** Si la diferencia desde donde empieza a saltar a donde acaba es mayor a 30,  muerto **/
			if (Math.abs(posicion_final_y-posicion_inicial_y) > DISTANCIA_MUERTO){   
				/** Si esta muerto, parar la musica, y realizar el tratamiento de Mario muerto. **/
				mario.pararSonido();
				mario.Muriendo();
			}
	
			/** Si Mario no esta muriendo, poner que ya deja de saltar **/
			if (!mario.isMuriendo()){
				
				mario.setSaltando(false);
				
				/** Reproducir sonido de caminar si se esta presionando la tecla de moverse **/
				if (mario.isMoviendose() & !mario.isSaltando()){
					mario.escucharSonido("walking", Clip.LOOP_CONTINUOUSLY);
				}
				t.stop();
	
			}
				/** Quitar los incrementos de movimiento de salto **/
				mario.setIncrementoSalto(0);
				mario.setDesplazamientoSalto(0);
				t.stop();
			
			
			
			
		}
		
	}


	/** Si durante el salto, chocas con los limites de la pantalla, debes retroceder en el eje X en vez de avanzar en el sentido del salto 
	 * 
	 */
	@Override
	public void actionPerformed(ActionEvent arg0) {
		if ((mario.detectarColision_dch(mario.getEsquina()))|(mario.detectarColision_izq(mario.getEsquina()))){
			mario.setDesplazamientoSalto(-incremento_x);
			t.stop();
		}else if ((mario.detectarColision_dch(mario.getCentroMario()))|(mario.detectarColision_izq(mario.getCentroMario()))){
			mario.setDesplazamientoSalto(-incremento_x);
			t.stop();
		}
	}

	public boolean isEn_ascensor() {
		return en_ascensor;
	}

	public void setEn_ascensor(boolean en_ascensor) {
		this.en_ascensor = en_ascensor;
	}
	
	
	


}
